#include <sdk.h>
#include "abbreviationsconfigpanel.h"
#include "M_Code_colourmanager.h"

BEGIN_EVENT_TABLE( AbbreviationsConfigPanel, cbConfigurationPanel )
END_EVENT_TABLE()

AbbreviationsConfigPanel::AbbreviationsConfigPanel( wxWindow* parent, Abbreviations* plugin ) : m_AutoCompTextControl( nullptr ), M_Code_Plugin( plugin ) {
  wxXmlResource* xml_res = wxXmlResource::Get();
  wxString resPath = ConfigManager::GetDataFolder() + _T( "/配置缩写词.xrc" ) ;
  xml_res->Load( resPath );
  if( !xml_res->LoadObject( this, parent, _T( "AbbreviationsConfigPanel" ), _T( "wxPanel" ) ) ) {
    return;
  }
  m_LanguageCmb = XRCCTRL( *this, "cmbAutoCompLanguage", wxComboBox );
  FillLangugages();
  m_LanguageCmb->SetSelection( 0 );
  m_LastAutoCompLanguage = defaultLanguageStr;
  InitCompText();
  m_Keyword = XRCCTRL( *this, "lstAutoCompKeyword", wxListBox );
  m_Keyword->Clear();
  m_pCurrentAutoCompMap = M_Code_Plugin->m_AutoCompLanguageMap[defaultLanguageStr];
  FillKeywords();
  Connect( XRCID( "lstAutoCompKeyword" ), wxEVT_COMMAND_LISTBOX_SELECTED, ( wxObjectEventFunction )&AbbreviationsConfigPanel::OnAutoCompKeyword );
  Connect( XRCID( "btnAutoCompAdd" ), wxEVT_COMMAND_BUTTON_CLICKED, ( wxObjectEventFunction )&AbbreviationsConfigPanel::OnAutoCompAdd );
  Connect( XRCID( "btnAutoCompDelete" ), wxEVT_COMMAND_BUTTON_CLICKED, ( wxObjectEventFunction )&AbbreviationsConfigPanel::OnAutoCompDelete );
  Connect( XRCID( "cmbAutoCompLanguage" ), wxEVT_COMMAND_COMBOBOX_SELECTED, ( wxObjectEventFunction )&AbbreviationsConfigPanel::OnLanguageSelect );
  Connect( XRCID( "btnAutoCompAddLanguage" ), wxEVT_COMMAND_BUTTON_CLICKED, ( wxObjectEventFunction )&AbbreviationsConfigPanel::OnLanguageAdd );
  Connect( XRCID( "btnAutoCompCopyLanguage" ), wxEVT_COMMAND_BUTTON_CLICKED, ( wxObjectEventFunction )&AbbreviationsConfigPanel::OnLanguageCopy );
  Connect( XRCID( "btnAutoCompDelLanguage" ), wxEVT_COMMAND_BUTTON_CLICKED, ( wxObjectEventFunction )&AbbreviationsConfigPanel::OnLanguageDelete );
}

AbbreviationsConfigPanel::~AbbreviationsConfigPanel() {
  Disconnect( XRCID( "lstAutoCompKeyword" ), wxEVT_COMMAND_LISTBOX_SELECTED, ( wxObjectEventFunction )&AbbreviationsConfigPanel::OnAutoCompKeyword );
  Disconnect( XRCID( "btnAutoCompAdd" ), wxEVT_COMMAND_BUTTON_CLICKED, ( wxObjectEventFunction )&AbbreviationsConfigPanel::OnAutoCompAdd );
  Disconnect( XRCID( "btnAutoCompDelete" ), wxEVT_COMMAND_BUTTON_CLICKED, ( wxObjectEventFunction )&AbbreviationsConfigPanel::OnAutoCompDelete );
  Disconnect( XRCID( "cmbAutoCompLanguage" ), wxEVT_COMMAND_COMBOBOX_SELECTED, ( wxObjectEventFunction )&AbbreviationsConfigPanel::OnLanguageSelect );
  Disconnect( XRCID( "btnAutoCompAddLanguage" ), wxEVT_COMMAND_BUTTON_CLICKED, ( wxObjectEventFunction )&AbbreviationsConfigPanel::OnLanguageAdd );
  Disconnect( XRCID( "btnAutoCompCopyLanguage" ), wxEVT_COMMAND_BUTTON_CLICKED, ( wxObjectEventFunction )&AbbreviationsConfigPanel::OnLanguageCopy );
  Disconnect( XRCID( "btnAutoCompDelLanguage" ), wxEVT_COMMAND_BUTTON_CLICKED, ( wxObjectEventFunction )&AbbreviationsConfigPanel::OnLanguageDelete );
  if( m_AutoCompTextControl ) {
    delete m_AutoCompTextControl;
  }
}

void AbbreviationsConfigPanel::InitCompText() {
  if( m_AutoCompTextControl ) {
    delete m_AutoCompTextControl;
  }
  m_AutoCompTextControl = new M_Code_StyledTextCtrl( this, wxID_ANY );
  m_AutoCompTextControl->SetTabWidth( 4 );
  m_AutoCompTextControl->SetMarginType( 0, wxSCI_MARGIN_NUMBER );
  m_AutoCompTextControl->SetMarginWidth( 0, 32 );
  m_AutoCompTextControl->SetViewWhiteSpace( 1 );
  m_AutoCompTextControl->SetMinSize( wxSize( 50, 50 ) );
  wxColor ccolor = Manager::Get()->GetColourManager()->GetColour( _T( "editor_caret" ) );
  m_AutoCompTextControl->SetCaretForeground( ccolor );
  ApplyColours();
  wxXmlResource::Get()->AttachUnknownControl( _T( "txtAutoCompCode" ), m_AutoCompTextControl );
}

void AbbreviationsConfigPanel::ApplyColours() {
  EditorColourSet* colour_set = Manager::Get()->GetEditorManager()->GetColourSet();
  if( colour_set ) {
    wxString FontString = Manager::Get()->GetConfigManager( _T( "editor" ) )->Read( _T( "/font" ), wxEmptyString );
    wxFont tmpFont( 10, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL );
    if( !FontString.IsEmpty() ) {
      wxNativeFontInfo nfi;
      nfi.FromString( FontString );
      tmpFont.SetNativeFontInfo( nfi );
    }
    if( m_AutoCompTextControl ) {
      m_AutoCompTextControl->StyleSetFont( wxSCI_STYLE_DEFAULT, tmpFont );
      colour_set->Apply( colour_set->GetHighlightLanguage( _T( "C/C++" ) ), m_AutoCompTextControl );
    }
  }
}

void AbbreviationsConfigPanel::AutoCompUpdate( const wxString& key, const wxString& lang ) {
  if( !key.IsEmpty() ) {
    AutoCompleteMap* compMap = M_Code_Plugin->m_AutoCompLanguageMap[lang];
    wxString code = m_AutoCompTextControl->GetText();
    code.Replace( _T( "\r\n" ), _T( "\n" ) );
    code.Replace( _T( "\r" ),   _T( "\n" ) );
    ( *compMap )[key] = code;
  }
}

void AbbreviationsConfigPanel::OnAutoCompAdd( M_Code_unused wxCommandEvent& event ) {
  wxString key = cbGetTextFromUser( _T( "输入新关键字" ), _T( "添加关键字" ) );
  if( !key.IsEmpty() ) {
    AutoCompleteMap::iterator it = m_pCurrentAutoCompMap->find( key );
    if( it != m_pCurrentAutoCompMap->end() ) {
      msging( _T( "这个关键字已经存在!" ), _T( "错误" ), wxICON_ERROR, this );
      return;
    }
    ( *m_pCurrentAutoCompMap )[key] = wxEmptyString;
    int sel = m_Keyword->Append( key );
    m_Keyword->SetSelection( sel );
    m_LastAutoCompKeyword = m_Keyword->GetStringSelection();
    AutoCompUpdate( m_LastAutoCompKeyword, m_LanguageCmb->GetValue() );
    m_AutoCompTextControl->SetText( wxEmptyString );
  }
}

void AbbreviationsConfigPanel::OnAutoCompDelete( M_Code_unused wxCommandEvent& event ) {
  if( m_Keyword->GetSelection() == -1 ) {
    return;
  }
  if( msging( _T( "是否确实要删除此关键字?" ), _T( "审查" ), wxICON_QUESTION | wxYES_NO, this ) == wxID_NO ) {
    return;
  }
  int delsel = m_Keyword->GetSelection();
  AutoCompleteMap::iterator it = m_pCurrentAutoCompMap->find( m_Keyword->GetString( delsel ) );
  if( it != m_pCurrentAutoCompMap->end() ) {
    int sel = delsel + 1;
    if( sel >= ( int )( m_Keyword->GetCount() ) ) {
      sel = m_Keyword->GetCount() - 2;
    }
    m_Keyword->SetSelection( sel );
    m_LastAutoCompKeyword = m_Keyword->GetStringSelection();
    if( sel >= 0 ) {
      m_AutoCompTextControl->SetText( ( *m_pCurrentAutoCompMap )[m_Keyword->GetString( sel )] );
    } else {
      m_AutoCompTextControl->SetText( wxEmptyString );
    }
    m_Keyword->Delete( delsel );
    m_pCurrentAutoCompMap->erase( it );
  }
}

void AbbreviationsConfigPanel::OnAutoCompKeyword( M_Code_unused wxCommandEvent& event ) {
  if( m_LastAutoCompKeyword.IsSameAs( m_Keyword->GetStringSelection() ) && m_LastAutoCompLanguage.IsSameAs( m_LanguageCmb->GetValue() ) ) {
    return;
  }
  AutoCompUpdate( m_LastAutoCompKeyword, m_LastAutoCompLanguage );
  m_LastAutoCompKeyword  = m_Keyword->GetStringSelection();
  if( !m_LastAutoCompKeyword.IsEmpty() ) {
    m_AutoCompTextControl->SetText( ( *m_pCurrentAutoCompMap )[m_LastAutoCompKeyword] );
  } else {
    m_AutoCompTextControl->SetText( wxEmptyString );
  }
  m_LastAutoCompLanguage = m_LanguageCmb->GetValue();
}

void AbbreviationsConfigPanel::OnApply() {
  AutoCompUpdate( m_Keyword->GetStringSelection(), m_LanguageCmb->GetValue() );
  for( AutoCompLanguageMap::iterator it = M_Code_Plugin->m_AutoCompLanguageMap.begin(); it != M_Code_Plugin->m_AutoCompLanguageMap.end(); ++it ) {
    Abbreviations::ExchangeTabAndSpaces( *it->second );
  }
}

void AbbreviationsConfigPanel::OnCancel() {
}

wxString AbbreviationsConfigPanel::GetTitle() const {
  return _T( "Abbreviations" );
}

wxString AbbreviationsConfigPanel::GetBitmapBaseName() const {
  return _T( "abbrev" );
}

void AbbreviationsConfigPanel::FillLangugages() {
  m_LanguageCmb->Clear();
  wxArrayString langs;
  AutoCompLanguageMap::iterator it;
  for( it = M_Code_Plugin->m_AutoCompLanguageMap.begin(); it != M_Code_Plugin->m_AutoCompLanguageMap.end(); ++it ) {
    langs.Add( it->first );
  }
  langs.Sort();
  m_LanguageCmb->Append( langs );
}

void AbbreviationsConfigPanel::FillKeywords() {
  m_Keyword->Clear();
  for( AutoCompleteMap::iterator it = m_pCurrentAutoCompMap->begin(); it != m_pCurrentAutoCompMap->end(); ++it ) {
    m_Keyword->Append( it->first );
  }
  if( !m_pCurrentAutoCompMap->empty() ) {
    m_Keyword->SetSelection( 0 );
    m_LastAutoCompKeyword = m_Keyword->GetStringSelection();
    m_AutoCompTextControl->SetText( ( *m_pCurrentAutoCompMap )[m_Keyword->GetString( m_Keyword->GetSelection() )] );
  } else {
    m_LastAutoCompKeyword = wxEmptyString;
    m_AutoCompTextControl->SetText( wxEmptyString );
  }
}

void AbbreviationsConfigPanel::OnLanguageSelect( M_Code_unused wxCommandEvent& event ) {
  LanguageSelected();
}

void AbbreviationsConfigPanel::LanguageSelected() {
  AutoCompUpdate( m_LastAutoCompKeyword, m_LastAutoCompLanguage );
  Abbreviations::ExchangeTabAndSpaces( *m_pCurrentAutoCompMap );
  wxString lang = m_LanguageCmb->GetValue();
  m_pCurrentAutoCompMap = M_Code_Plugin->m_AutoCompLanguageMap[lang];
  FillKeywords();
  m_LastAutoCompLanguage = lang;
}

void AbbreviationsConfigPanel::OnLanguageAdd( M_Code_unused wxCommandEvent& event ) {
  LanguageAdd();
}

int AbbreviationsConfigPanel::LanguageAdd() {
  EditorColourSet* colSet = Manager::Get()->GetEditorManager()->GetColourSet();
  if( colSet ) {
    colSet = new EditorColourSet( *colSet );
  } else {
    colSet = new EditorColourSet();
  }
  wxArrayString newLangs;
  wxArrayString langs = colSet->GetAllHighlightLanguages();
  for( unsigned int i = 0; i < langs.GetCount(); ++i ) {
    if( M_Code_Plugin->m_AutoCompLanguageMap.find( langs[i] ) == M_Code_Plugin->m_AutoCompLanguageMap.end() && !langs[i].IsSameAs( _T( "Fortran77" ) ) ) {
      newLangs.Add( langs[i] );
    }
  }
  newLangs.Sort();
  int sel = cbGetSingleChoiceIndex( _T( "选择语言:" ), _T( "Languages" ), newLangs, this );
  if( sel == -1 ) {
    return sel;
  }
  M_Code_Plugin->m_AutoCompLanguageMap[newLangs[sel]] = new AutoCompleteMap();
  FillLangugages();
  m_LanguageCmb->SetValue( newLangs[sel] );
  LanguageSelected();
  return 0;
}

void AbbreviationsConfigPanel::OnLanguageCopy( M_Code_unused wxCommandEvent& event ) {
  wxString langCopy = m_LanguageCmb->GetValue();
  if( LanguageAdd() == -1 ) {
    return;
  }
  wxString langNew = m_LanguageCmb->GetValue();
  AutoCompleteMap* pMapCopy = M_Code_Plugin->m_AutoCompLanguageMap[langCopy];
  AutoCompleteMap* pMapNew  = M_Code_Plugin->m_AutoCompLanguageMap[langNew];
  for( AutoCompleteMap::iterator it = pMapCopy->begin(); it != pMapCopy->end(); ++it ) {
    ( *pMapNew )[it->first] = it->second;
  }
  FillKeywords();
}

void AbbreviationsConfigPanel::OnLanguageDelete( M_Code_unused wxCommandEvent& event ) {
  wxString lang = m_LanguageCmb->GetValue();
  if( lang.IsSameAs( defaultLanguageStr ) || lang.IsSameAs( _T( "Fortran" ) ) ) {
    msging( _T( "缩写词 " ) + lang + _T( " 无法删除语言!" ), _T( "错误" ),
            wxICON_ERROR | wxOK, this );
    return;
  }
  if( msging( _T( "是否确实要删除 " ) + lang + _T( " 语言?" ), _T( "审查" ),
              wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT, this ) == wxID_NO ) {
    return;
  }
  m_LanguageCmb->SetSelection( 0 );
  LanguageSelected();
  AutoCompleteMap* pAutoCompleteMap = M_Code_Plugin->m_AutoCompLanguageMap[lang];
  pAutoCompleteMap->clear();
  delete pAutoCompleteMap;
  M_Code_Plugin->m_AutoCompLanguageMap.erase( lang );
  FillLangugages();
  m_LanguageCmb->SetSelection( 0 );
}
